﻿@page "/device-detail"
@using ExampleBlazor.Data
@using InfluxDB.Client.Api.Domain
@using InfluxDB.Client.Core.Flux.Domain
@using Radzen
@using System.Globalization

<PageTitle>Device Detail</PageTitle>

<div class="row my-xl-3">
    <div class="col-xl-12">
        <RadzenCard class="pb-5 fill">
            <div class="row">
                <div class="col-6">
                    <h2 class="h1_blue">Device<span class="h1_pink">Detail</span></h2>
                </div>
                <div class="col-6 text-end">
                    @if (BucketList == null)
                    {
                        <select class="card-select" @bind="SelectedBucket">
                            <option>-- bucket --</option>
                        </select>
                    }
                    else
                    {
                        <select class="card-select" @bind="SelectedBucket">
                            <option>-- bucket --</option>

                            @foreach (var bucket in BucketList)
                            {
                                <option value="@bucket.Name">@bucket.Name</option>
                            }
                        </select>
                    }
                    @if (DeviceList == null)
                    {
                        <select class="card-select" @bind="SelectedDevice">
                            <option>-- deviceId --</option>
                        </select>
                    }
                    else
                    {
                        <select class="card-select" @bind="SelectedDevice">
                            <option>-- deviceId --</option>

                            @foreach (var device in DeviceList)
                            {
                                <option value="@device!.Values.First(rec => rec.Key == "deviceId").Value">@device.Values.First(rec => rec.Key == "deviceId").Value</option>
                            }
                        </select>
                    }
                    <RadzenButton Click="WriteEmulatedData" Icon="edit_note" IsBusy="@WriteEmulatedDataBusy"
                                  ButtonStyle="ButtonStyle.Light"/>
                    <RadzenButton Click="RefreshBuckets" Icon="refresh" IsBusy="@RefreshBucketsBusy"
                                  ButtonStyle="ButtonStyle.Light"/>
                </div>
            </div>
            <hr/>

            <div class="row align-self-center" style="width: 50%; max-width: 700px; min-width: 500px">
                <RadzenCard>
                    <div class="row">
                        <div class="col-3 align-self-center">
                            <RadzenImage Path="/assets/IoT-hl.svg" Class="rounded-circle float-left mr-3" Style="width: 100%; height: 100px;"/>
                        </div>
                        <div class="col-9">
                            <div class="row">
                                <div class="col-md-8 text-truncate">
                                    <b>Device Configuration:</b>
                                </div>
                            </div>
                            <hr style="border: none; background-color: rgba(0, 0, 0, .08); height: 1px; margin: 1rem 0;"/>
                            <div class="row">
                                <div class="col-6">
                                    <label class="mt-3">DeviceID</label>
                                    <div>@SelectedDevice</div>
                                    <label class="mt-3">Bucket</label>
                                    <div>@SelectedBucket</div>
                                </div>
                                <div class="col-6">
                                    <label class="mt-3">Url</label>
                                    <div>@InfluxModel.Client.Url</div>
                                    <label class="mt-3">Registration Time</label>
                                    <div>@SelectedDeviceCreatedAt</div>
                                </div>
                            </div>
                        </div>
                    </div>
                </RadzenCard>
            </div>


            <div class="row">
                <div class="col-12 my-3">
                    <RadzenDataGrid Data="@Measurements" TItem="FluxTable" PagerPosition="PagerPosition.Bottom" AllowPaging="true" AllowSorting="false">
                        <Columns>
                            <RadzenDataGridColumn TItem="FluxTable" Property="Field" Title="Field">
                                <Template Context="table">
                                    @table.Records.FirstOrDefault()?.Values.FirstOrDefault(rec => rec.Key == "_field").Value
                                </Template>
                            </RadzenDataGridColumn>
                            <RadzenDataGridColumn TItem="FluxTable" Property="Min" Title="Min">
                                <Template Context="table">
                                    @table.Records.FirstOrDefault()?.Values.FirstOrDefault(rec => rec.Key == "minValue").Value
                                </Template>
                            </RadzenDataGridColumn>
                            <RadzenDataGridColumn TItem="FluxTable" Property="Max" Title="Max">
                                <Template Context="table">
                                    @table.Records.FirstOrDefault()?.Values.FirstOrDefault(rec => rec.Key == "maxValue").Value
                                </Template>
                            </RadzenDataGridColumn>
                            <RadzenDataGridColumn TItem="FluxTable" Property="MaxTime" Title="Max time">
                                <Template Context="table">
                                    @FormatDateTime(@table.Records.FirstOrDefault()?.Values.FirstOrDefault(rec => rec.Key == "maxTime").Value)
                                </Template>
                            </RadzenDataGridColumn>
                            <RadzenDataGridColumn TItem="FluxTable" Property="EntryCount" Title="Entry count">
                                <Template Context="table">
                                    @table.Records.FirstOrDefault()?.Values.FirstOrDefault(rec => rec.Key == "count").Value
                                </Template>
                            </RadzenDataGridColumn>
                        </Columns>
                    </RadzenDataGrid>
                </div>
            </div>
        </RadzenCard>
    </div>
</div>

<div class="row my-xl-3 my-1">
    <div class="col-xl-12">
        <RadzenCard class="pb-5 fill">
            <div class="row">
                <div class="col-6">
                    <h2 class="h1_blue">Measurements<span class="h1_pink">Detail</span></h2>
                </div>
                <div class="col-6 text-end">
                    <select class="card-select" @bind="@SelectedTimeRange">
                        @foreach (var timeRange in _timeRangeList)
                        {
                            <option value="@timeRange.Value">@timeRange.Label</option>
                        }
                    </select>
                    <RadzenButton Click="RefreshData" Icon="refresh" IsBusy="@RefreshDataBusy"
                                  ButtonStyle="ButtonStyle.Light"/>
                </div>
            </div>
            <hr/>
            <div class="row">
                <div class="col-12">
                    <RadzenChart>
                        <RadzenLineSeries Smooth="true" Data="@LinqData" CategoryProperty="Timestamp"
                                          Title="Temperature" LineType="LineType.Solid"
                                          ValueProperty="Temperature" Stroke="#d30971" StrokeWidth="1"/>
                        <RadzenLineSeries Smooth="true" Data="@LinqData" CategoryProperty="Timestamp"
                                          Title="Humidity" LineType="LineType.Solid"
                                          ValueProperty="Humidity" Stroke=" #0071c1" StrokeWidth="1"/>
                    </RadzenChart>
                    <RadzenChart >
                        <RadzenLineSeries Smooth="true" Data="@LinqData" CategoryProperty="Timestamp"
                                          Title="Pressure" LineType="LineType.Solid"
                                          ValueProperty="Pressure" Stroke="#d30971" StrokeWidth="1"/>
                        <RadzenLineSeries Smooth="true" Data="@LinqData" CategoryProperty="Timestamp"
                                          Title="CO2" LineType="LineType.Solid"
                                          ValueProperty="Co2" Stroke=" #0071c1" StrokeWidth="1"/>
                        <RadzenLineSeries Smooth="true" Data="@LinqData" CategoryProperty="Timestamp"
                                          Title="TVOC" LineType="LineType.Solid"
                                          ValueProperty="Tvoc" Stroke="#020a47" StrokeWidth="1"/>
                    </RadzenChart>
                </div>
            </div>
            <div class="row">
                <div class="col-12 my-3">
                    <RadzenDataGrid Data="@LinqData" TItem="InfluxModel.MeasurementPoint"
                                    PagerPosition="PagerPosition.Bottom" AllowPaging="true" AllowSorting="true" PageSize="10">
                        <Columns>
                            <RadzenDataGridColumn TItem="InfluxModel.MeasurementPoint"
                                                  Property="Timestamp" Title="Timestamp"/>
                            <RadzenDataGridColumn TItem="InfluxModel.MeasurementPoint"
                                                  Property="Temperature" Title="Temperature"/>
                            <RadzenDataGridColumn TItem="InfluxModel.MeasurementPoint"
                                                  Property="Humidity" Title="Humidity"/>
                            <RadzenDataGridColumn TItem="InfluxModel.MeasurementPoint"
                                                  Property="Pressure" Title="Pressure"/>
                            <RadzenDataGridColumn TItem="InfluxModel.MeasurementPoint"
                                                  Property="Co2" Title="CO2"/>
                            <RadzenDataGridColumn TItem="InfluxModel.MeasurementPoint"
                                                  Property="Tvoc" Title="TVOC"/>
                        </Columns>
                    </RadzenDataGrid>
                </div>
            </div>
        </RadzenCard>
    </div>
</div>

@code {

    protected override async Task OnInitializedAsync()
    {
        BucketList = await InfluxModel.FetchBuckets();
    }

    private List<Bucket>? _bucketList;

    private List<Bucket>? BucketList
    {
        get => _bucketList;
        set
        {
            _bucketList = value;
            StateHasChanged();
            if (value == null || value.Count < 1)
                SelectedBucket = "";
            else if (!string.IsNullOrEmpty(SelectedBucket) &&
                     value.FirstOrDefault(bucket => bucket.Name == SelectedBucket) != null)
                SelectedBucket = SelectedBucket;
            else if (string.IsNullOrEmpty(SelectedBucket) &&
                     value.FirstOrDefault(bucket => bucket.Name == "iot_center") != null)
                SelectedBucket = "iot_center";
            else SelectedBucket = value.FirstOrDefault()!.Name;
        }
    }

    private string? _selectedBucket;

    string? SelectedBucket
    {
        get => _selectedBucket;
        set
        {
            _selectedBucket = value;
            FetchDevices(value);
        }
    }

    private List<FluxRecord?>? _deviceList;

    private List<FluxRecord?>? DeviceList
    {
        get => _deviceList;
        set
        {
            _deviceList = value;
            StateHasChanged();
            if (value == null || value.Count < 1)
                SelectedDevice = "";
            else if (string.IsNullOrEmpty(SelectedDevice) ||
                     value.FirstOrDefault(dev => dev!.Values.FirstOrDefault(rec => rec.Key == "deviceId").Value.ToString() == SelectedDevice) == null)
            {
                var device = value.FirstOrDefault(dev => dev!.Values.FirstOrDefault(rec => rec.Key == "deviceId").Value.ToString() == "virtual_device");
                SelectedDevice = device != null ?
                    device.Values.FirstOrDefault(rec => rec.Key == "deviceId").Value.ToString()
                    : value.FirstOrDefault()!.GetValueByKey("deviceId").ToString();
            }
        }
    }

    private string? _selectedDevice;

    private string? SelectedDevice
    {
        get => _selectedDevice;
        set
        {
            _selectedDevice = value;
            StateHasChanged();
            RefreshDevice();
        }
    }

    private string? _selectedDeviceCreatedAt;

    private string? SelectedDeviceCreatedAt
    {
        get => _selectedDeviceCreatedAt;
        set
        {
            _selectedDeviceCreatedAt = value;
            StateHasChanged();
        }
    }

    private bool _writeEmulatedDataBusy;

    private bool WriteEmulatedDataBusy
    {
        get => _writeEmulatedDataBusy;
        set
        {
            _writeEmulatedDataBusy = value;
            StateHasChanged();
        }
    }

    private bool _refreshBucketsBusy;

    private bool RefreshBucketsBusy
    {
        get => _refreshBucketsBusy;
        set
        {
            _refreshBucketsBusy = value;
            StateHasChanged();
        }
    }

    private List<FluxTable>? _measurements;

    private List<FluxTable>? Measurements
    {
        get => _measurements;
        set
        {
            _measurements = value;
            StateHasChanged();
        }
    }

    private bool _refreshDataBusy;

    private bool RefreshDataBusy
    {
        get => _refreshDataBusy;
        set
        {
            _refreshDataBusy = value;
            StateHasChanged();
        }
    }

    private List<InfluxModel.MeasurementPoint>? _linqData;

    private List<InfluxModel.MeasurementPoint>? LinqData
    {
        get => _linqData;
        set
        {
            _linqData = value;
            StateHasChanged();
        }
    }

    private readonly List<TimeRange> _timeRangeList = new()
    {
        new TimeRange { Label = "Past 5m", Value = "5m" },
        new TimeRange { Label = "Past 15m", Value = "15m" },
        new TimeRange { Label = "Past 1h", Value = "1h" },
        new TimeRange { Label = "Past 6h", Value = "6h" },
        new TimeRange { Label = "Past 1d", Value = "1d" },
        new TimeRange { Label = "Past 3d", Value = "3d" },
        new TimeRange { Label = "Past 7d", Value = "7d" },
        new TimeRange { Label = "Past 30d", Value = "30d" }
    };


    private string _selectedTimeRange = "1d";

    private string SelectedTimeRange
    {
        get => _selectedTimeRange;
        set
        {
            _selectedTimeRange = value;
            StateHasChanged();
            RefreshData();
        }
    }

    private async void FetchDevices(string? value)
    {
        if (!string.IsNullOrEmpty(value))
        {
            var tables = await InfluxModel.FetchDeviceList(value);
            if (tables != null)
            {
                var records = tables.Select(table => table.Records
                    .FirstOrDefault(rec => rec.Values.ContainsKey("deviceId"))).ToList();
                DeviceList = records;
            }
        }
        else
        {
            DeviceList = new List<FluxRecord>()!;
        }
    }

    private async void WriteEmulatedData()
    {
        WriteEmulatedDataBusy = true;
        if (SelectedBucket != null && !string.IsNullOrEmpty(SelectedDevice))
            await InfluxModel.WriteEmulatedData(SelectedDevice, SelectedBucket);

        WriteEmulatedDataBusy = false;

        RefreshBuckets();
    }

    private async void RefreshBuckets()
    {
        RefreshBucketsBusy = true;

        BucketList = await InfluxModel.FetchBuckets();

        RefreshDevice();

        RefreshBucketsBusy = false;
    }

    private async void RefreshDevice()
    {
        RefreshBucketsBusy = true;

        if (SelectedBucket != null && !string.IsNullOrEmpty(SelectedDevice))
        {
            SelectedDeviceCreatedAt = (await InfluxModel.FetchDeviceCreatedAt(SelectedBucket, SelectedDevice)).ToString(CultureInfo.InvariantCulture);
            Measurements = await InfluxModel.FetchMeasurements(SelectedBucket, SelectedDevice);
        }
        else Measurements = new List<FluxTable>();

        RefreshData();

        RefreshBucketsBusy = false;
    }

    private async void RefreshData()
    {
        RefreshDataBusy = true;

        LinqData = await InfluxModel.FetchDataLinq(SelectedBucket, SelectedDevice, SelectedTimeRange);

        RefreshDataBusy = false;
    }

    string FormatDateTime(object? value)
    {
        return value != null ? Convert.ToDateTime(value.ToString()).ToString(CultureInfo.InvariantCulture) : string.Empty;
    }

    class TimeRange
    {
        public string? Label;
        public string? Value;
    }
    } 